#define TRACKFILTER_PACK_OPTION "pack"
#define TRACKFILTER_SPLIT_OPTION "split"
+#define TRACKFILTER_SDIST_OPTION "sdistance"
#define TRACKFILTER_TITLE_OPTION "title"
#define TRACKFILTER_MERGE_OPTION "merge"
#define TRACKFILTER_NAME_OPTION "name"
static char *opt_merge = NULL;
static char *opt_pack = NULL;
static char *opt_split = NULL;
+static char *opt_sdistance = NULL;
static char *opt_move = NULL;
static char *opt_title = NULL;
static char *opt_start = NULL;
{TRACKFILTER_SPLIT_OPTION, &opt_split,
"Split by date or time interval (see README)", NULL,
ARGTYPE_STRING, ARG_NOMINMAX},
+ {TRACKFILTER_SDIST_OPTION, &opt_sdistance,
+ "Split by distance", NULL,
+ ARGTYPE_STRING, ARG_NOMINMAX},
{TRACKFILTER_MERGE_OPTION, &opt_merge,
"Merge multiple tracks for the same way", NULL, ARGTYPE_STRING,
ARG_NOMINMAX},
static int track_ct = 0;
static int track_pts = 0;
static int opt_interval = 0;
+static int opt_distance = 0;
/*******************************************************************************
* helpers
queue *elem, *tmp;
int i, j;
float interval = -1;
+ float distance = -1;
if (count <= 1) return;
/* check additional options */
- opt_interval = ((strlen(opt_split) > 0) && (0 != strcmp(opt_split, TRACKFILTER_SPLIT_OPTION)));
+ opt_interval = (opt_split && (strlen(opt_split) > 0) && (0 != strcmp(opt_split, TRACKFILTER_SPLIT_OPTION)));
+ opt_distance = (opt_sdistance && (strlen(opt_sdistance) > 0) && (0 != strcmp(opt_sdistance, TRACKFILTER_SDIST_OPTION)));
if (opt_interval != 0)
{
float base;
- char dhms;
+ char unit;
switch(strlen(opt_split))
{
break; /* ? */
case 1:
- dhms = *opt_split;
+ unit = *opt_split;
interval = 1;
break;
default:
- i = sscanf(opt_split,"%f%c", &interval, &dhms);
+ i = sscanf(opt_split,"%f%c", &interval, &unit);
if (i == 0)
{
/* test reverse order */
- i = sscanf(opt_split,"%c%f", &dhms, &interval);
+ i = sscanf(opt_split,"%c%f", &unit, &interval);
}
if ((i != 2) || (interval <= 0))
{
break;
}
- switch(tolower(dhms))
+ switch(tolower(unit))
{
case 's':
base = 1;
break;
}
#ifdef TRACKF_DBG
- printf(MYNAME ": dhms \"%c\", interval %g -> %g\n", dhms, interval, base * interval);
+ printf(MYNAME ": unit \"%c\", interval %g -> %g\n", unit, interval, base * interval);
#endif
interval *= base;
}
+ if (opt_distance != 0)
+ {
+ float base;
+ char unit;
+
+ switch(strlen(opt_sdistance))
+ {
+ case 0:
+ fatal(MYNAME ": No distance specified.\n");
+ break; /* ? */
+
+ case 1:
+ unit = *opt_sdistance;
+ distance = 1;
+ break;
+
+ default:
+ i = sscanf(opt_sdistance,"%f%c", &distance, &unit);
+ if (i == 0)
+ {
+ /* test reverse order */
+ i = sscanf(opt_sdistance,"%c%f", &unit, &distance);
+ }
+ if ((i != 2) || (distance <= 0))
+ {
+ fatal(MYNAME ": invalid distance specified, must be one a positive number.\n");
+ }
+ break;
+ }
+
+ switch(tolower(unit))
+ {
+ case 'k': /* kilometers */
+ base = 0.6214;
+ break;
+ case 'm': /* miles */
+ base = 1;
+ break;
+ default:
+ fatal(MYNAME ": invalid distance specified, must be one of [km].\n");
+ break;
+ }
+#ifdef TRACKF_DBG
+ printf(MYNAME ": unit \"%c\", distance %g -> %g\n", unit, distance, base * distance);
+#endif
+ distance *= base;
+ }
+
trackfilter_split_init_rte_name(master, track_list[0].first_time);
buff = (waypoint **) xcalloc(count, sizeof(*buff));
{
int new_track_flag;
- if (opt_interval == 0)
+ if ((opt_interval == 0) && (opt_distance == 0))
{
struct tm t1, t2;
}
else
{
- float tr_interval;
+ new_track_flag = 1;
- tr_interval = difftime(buff[j]->creation_time,buff[i]->creation_time);
- new_track_flag = ( tr_interval > interval );
+ if (distance > 0)
+ {
+ double rt1 = RAD(buff[i]->latitude);
+ double rn1 = RAD(buff[i]->longitude);
+ double rt2 = RAD(buff[j]->latitude);
+ double rn2 = RAD(buff[j]->longitude);
+ double curdist = gcdist( rt1, rn1, rt2, rn2 );
+ curdist = radtomiles(curdist);
+ if ( curdist <= distance )
+ new_track_flag = 0;
#ifdef TRACKF_DBG
- if (new_track_flag != 0)
- printf(MYNAME ": split, %g > %g\n", tr_interval, interval );
+ else
+ printf(MYNAME ": sdistance, %g > %g\n", curdist, distance );
+#endif
+ }
+
+ if (interval > 0)
+ {
+ float tr_interval = difftime(buff[j]->creation_time,buff[i]->creation_time);
+ if ( tr_interval <= interval )
+ new_track_flag = 0;
+#ifdef TRACKF_DBG
+ else
+ printf(MYNAME ": split, %g > %g\n", tr_interval, interval );
#endif
+ }
+
}
if (new_track_flag != 0)
{
+#ifdef TRACKF_DBG
+ printf(MYNAME ": splitting new track\n" );
+#endif
curr = (route_head *) route_head_alloc();
trackfilter_split_init_rte_name(curr, buff[j]->creation_time);
track_add_head(curr);
return;
}
- if (opt_split != NULL)
+ if ((opt_split != NULL) || (opt_sdistance != NULL))
{
if (track_ct > 1)
fatal(MYNAME "-split: Cannot split more than one track, please pack (or merge) before!\n");
--- /dev/null
+ <para> The input track will be split into several tracks
+ if the distance between successive track points
+ is greater than the distance given as a parameter.
+ The distance must be numeric and can be in miles or kilometers,
+ expressed as one of the character "k", or "m".
+ If sdistance is given no parameters, this option has the same
+ effect as the split option without parameters. If there is more
+ than one track,
+ use the pack option before before using this.</para>
+
+ <para> For example, to split the track if the distance between
+ points is greater than 100 meters, use this:</para>
+ <screen format="linespecific">
+gpsbabel -t \
+ -i gpx -f in.gpx \
+ -x track,pack,sdistance=0.1k" \
+ -o gpx -F out.gpx
+</screen>
+ <para> The sdistance option can be combined with the split option.
+ The track then will be split only if both time and distance
+ interval exceeds the supplied values. This technique can be used to
+ filter out gaps from
+ the tracklog. The gap is kept only if the gps device is without
+ signal for longer time than that given and during that time it moves
+ a distance over that given.
+ This example splits the track
+ if the device is without signal for at least 5 minutes
+ and during this time moves more than 300 meters:</para>
+ <screen format="linespecific">
+gpsbabel -t \
+ -i gpx -f in.gpx \
+ -x track,pack,sdistance=0.3k,split=5m \
+ -o gpx -F out.gpx
+</screen>
+
+